﻿using Abp.Application.Services.Dto;
using Abp.AutoMapper;
using Abp.Domain.Repositories;
using Abp.Domain.Uow;
using Abp.EntityFrameworkCore.Repositories;
using Abp.UI;
using Hicap.AuthorizationServer.Core.Caches.Sys;
using Hicap.AuthorizationServer.Core.Caches.Sys.Interface;
using Hicap.AuthorizationServer.Core.Models.Sys;
using Hicap.AuthorizationServer.Sys.AppService.Interface;
using Hicap.AuthorizationServer.Sys.DTO.AuthObjectRoleRelateds;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;

namespace Hicap.AuthorizationServer.Sys.AppService
{
    /// <summary>
    /// AuthObjectRoleRelated应用层服务的接口实现方法
    /// </summary>

    public class AuthObjectRoleRelatedAppService
        : AuthorizationServerAppServiceBase<AuthObjectRoleRelated, AuthObjectRoleRelatedAppService, AuthObjectRoleRelatedEditDto, AuthObjectRoleRelatedListDto, AuthObjectRoleRelatedCacheItem>, IAuthObjectRoleRelatedAppService
    {
        #region Member

        private readonly IRepository<AuthObjectRoleRelated> _authobjectrolerelatedRepository;
        private readonly IAuthObjectCache _authObjectCache;
        private readonly IRoleCache _roleCache;
        private readonly IRepository<Role> _roleRepository;
        private readonly IRepository<AuthObject> _authObjectRepository;

        #endregion Member

        #region Constructor

        /// <summary>
        /// 构造函数
        /// </summary>
        public AuthObjectRoleRelatedAppService(IRepository<AuthObjectRoleRelated> authobjectrolerelatedRepository
            , IUnitOfWorkManager unitOfWorkManager,
            IAuthObjectRoleRelatedCache cache,
            IRepository<AuthObjectRoleRelated> repository, IAuthObjectCache authObjectCache, IRoleCache roleCache, IRepository<Role> roleRepository, IRepository<AuthObject> authObjectRepository)
            : base(repository, unitOfWorkManager, cache)
        {
            _authobjectrolerelatedRepository = authobjectrolerelatedRepository;
            _authObjectCache = authObjectCache;
            _roleCache = roleCache;
            _roleRepository = roleRepository;
            _authObjectRepository = authObjectRepository;
            ForeignKeys.Add(x => x.AuthObject);
            ForeignKeys.Add(x => x.Role);
            CreateActions.Add((SetAuthObjectRole));
            UpdateActions.Add((SetAuthObjectRoleId));
            CreateCheckActions.Add(IsDbExist);
        }

        #endregion Constructor

        #region WebApi

        /// <summary>
        /// 按照固定条件查询关系表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<AuthObjectRoleRelatedListDto>> PagedQueryDatas(AuthObjectRoleRelatedQueryDTO input)
        {
            //            PermissionCheck();
            //查询条件
            Func<AuthObjectRoleRelated, bool> query = (entity) =>
            {
                bool flag = true;
                if (input.RoleId.HasValue) flag = entity.Role.Id == input.RoleId && flag;
                if (input.AuthObjectId.HasValue) flag = entity.AuthObject.Id == input.AuthObjectId && flag;
                if (!string.IsNullOrEmpty(input.AuthObjectCode)) flag = entity.AuthObject != null && (entity.AuthObject.ObjectCode == input.AuthObjectCode && flag);
                if (!string.IsNullOrEmpty(input.RoleCode)) flag = entity.Role != null && (entity.Role.RoleCode == input.RoleCode && flag);
                if (!string.IsNullOrEmpty(input.AuthObjectName)) flag = entity.AuthObject != null && (entity.AuthObject.ObjectName.Contains(input.AuthObjectName) && flag);
                if (!string.IsNullOrEmpty(input.RoleName)) flag = entity.Role != null && (entity.Role.RoleName.Contains(input.RoleName) && flag);
                return flag;
            };

            //记录数
            int count = await _authobjectrolerelatedRepository.CountAsync(x => query(x));

            //查询结果
            List<AuthObjectRoleRelated> result = await _authobjectrolerelatedRepository.GetAllIncluding(x => x.Role, x => x.AuthObject).Where(x => query(x)).ToListAsync();

            //DTO Mapper
            List<AuthObjectRoleRelatedListDto> resultListDto = result.MapTo<List<AuthObjectRoleRelatedListDto>>();

            return new PagedResultDto<AuthObjectRoleRelatedListDto>(
                count,
                resultListDto
            );
        }

        #endregion WebApi

        #region Priavte Method

        /// <summary>
        /// 设置外键ID
        /// </summary>
        /// <param name="input"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        private void SetAuthObjectRoleId(AuthObjectRoleRelatedEditDto input, AuthObjectRoleRelated entity)
        {
            if (input.RoleId.HasValue) entity.Role.Id = input.RoleId.Value;
            if (input.AuthObjectId.HasValue) entity.AuthObject.Id = input.AuthObjectId.Value;
        }

        /// <summary>
        /// 设置外键
        /// </summary>
        /// <param name="input"></param>
        /// <param name="entity"></param>
        /// <returns></returns>
        private void SetAuthObjectRole(AuthObjectRoleRelatedEditDto input, AuthObjectRoleRelated entity)
        {
            DbContext db = _authobjectrolerelatedRepository.GetDbContext();
            if (input.RoleId.HasValue)
            {
                //                var roleCache = await _roleCache.GetAsync(input.RoleId.Value);
                //                var role = roleCache.MapTo<Role>();
                //                if (db.Entry(role).State == EntityState.Detached)
                //                {
                //                    //                    _roleRepository.DetachFromDbContext(role);
                //                    //                    role = _roleRepository.GetDbContext().Attach(role).Entity;
                //                    role = _roleRepository.GetDbContext().Entry(role).Entity;
                //                    var x = db.Entry(role).State;
                //                }
                Role role = _roleRepository.Get(input.RoleId.Value);
                entity.Role = role;
            }

            if (input.AuthObjectId.HasValue)
            {
                //                var authObjectCache = await _authObjectCache.GetAsync(input.AuthObjectId.Value);
                //                var authObject = authObjectCache.MapTo<AuthObject>();
                //                if (db.Entry(authObject).State != EntityState.Detached)
                //                {
                //                    _authObjectRepository.DetachFromDbContext(authObject);
                //                authObject = _authObjectRepository.GetDbContext().Attach(authObject).Entity;
                //                }
                AuthObject authObject = _authObjectRepository.Get(input.AuthObjectId.Value);
                entity.AuthObject = authObject;
            }
        }

        /// <summary>
        /// 重复值校验
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        private void IsDbExist(AuthObjectRoleRelated entity)
        {
            bool isDbExist = false;

            if (entity.Role != null & entity.AuthObject != null)
            {
                isDbExist = _authobjectrolerelatedRepository.GetAllIncluding(x => x.AuthObject, x => x.Role).Count(
                                x => x.Role.Id == entity.Role.Id && x.AuthObject.Id == entity.AuthObject.Id) > 0;
            }

            if (isDbExist)
                throw new UserFriendlyException($"SameRecordIsExist:Role,AuthObject");
        }

        #endregion Priavte Method
    }
}